﻿//    TestGenerator - experiment with piping data into ffmpeg in "pipefmt"
//    Copyright (C) 2012  Juergen Bohl

//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.

//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.

//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

namespace TestGenerator
{
    #region using directives
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    #endregion

    internal class FfmpegAVPipe : FfmpegPipeBase
    {
        /// <summary>
        /// The frameheader magic ('V','S','T','R','E','A','M','#').
        /// </summary>
        private static readonly byte[] FrameString = { 86, 83, 84, 82, 69, 65, 77, 35 };

        private VideoFormat videoFormat;
        private AudioFormat audioFormat;

        public void Init(VideoFormat vf, AudioFormat af)
        {
            this.InitializePipe();
            this.audioFormat = af;
            this.videoFormat = vf;
        }

        public void WriteHeader()
        {
            this.IntWriteHeader();
        }

        public void AddVideoFrame(byte[] buffer)
        {
            this.WriteVStreamHeader(0);
            this.AddToPipe(buffer);
        }

        public void AddAudio(byte[] buffer)
        {
            this.WriteAStreamHeader(0, 1920);
            this.AddToPipe(buffer);
        }

        private void IntWriteHeader()
        {
            PipeFormatHelper.WriteHeader(
                                        data =>
                                        {
                                            this.AddToPipe(data);
                                            return true;
                                        },
                                        this.videoFormat != null ? Enumerable.Repeat(this.videoFormat, 1) : null,
                                        this.audioFormat != null ? Enumerable.Repeat(this.audioFormat, 1) : null);
        }

        private void WriteVStreamHeader(int streamNo)
        {
            // VSTREAM#0:\n
            byte[] buffer = new byte[FrameString.Length + 3];
            Buffer.BlockCopy(FrameString, 0, buffer, 0, FrameString.Length);
            buffer[FrameString.Length] = (byte)(48 + streamNo);
            buffer[FrameString.Length + 1] = 0x3a;  // ':'
            buffer[FrameString.Length + 2] = 0x0a;
            this.AddToPipe(buffer);
        }

        private void WriteAStreamHeader(int streamNo,int samplesCount)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("ASTREAM#{0}:C={1}\n", streamNo, samplesCount);
            byte[] fmtAscii = Encoding.ASCII.GetBytes(sb.ToString());
            this.AddToPipe(fmtAscii);
        }
    }
}
